#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <list>

int f(int a, int b)
{
    return a + b;
}
struct Functor
{
public:
    int operator()(int a, int b)
    {
        return a + b;
    }
};
class Plus
{
public:
    static int plusi(int a, int b)
    {
        return a + b;
    }
    double plusd(double a, double b)
    {
        return a + b;
    }
};

int *add(int a)
{
    static int sum = 0;
    int *ret = &sum;

    for (size_t i = 1; i <= a; i++)
    {
        sum += i;
    }
    printf("result:%d\n", *ret);
    return ret;
}

void Test1()
{
    int *p = add(10);
    std::cout << *p << std::endl;
}

int max(int a, int b)
{
    return a > b ? a : b;
}

void Test2()
{
    // ret(*p)(args,...)
    int (*p)(int, int);
    p = max;

    std::cout << p(10, 20) << std::endl;
}

int callback(int a, int b, int (*p)(int, int))
{
    return p(a, b);
}

template <typename T>
T callback2(T n, T *(*p)(T))
{
    return *p(n);
}

void Test3()
{
    //  printf("max:%d\n", callback(10, 20, max));
    printf("result:%d\n", callback2(10, add));
}

template <typename T>
class Max
{
public:
    bool operator()(const T &a, const T &b) const
    {
        if ((a % 2 == 0 && b % 2 == 0) || (a % 2 != 0 && b % 2 != 0))
        {
            return a > b;
        }
        else if (a % 2 == 0)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

void Test4()
{

    std::vector<int> vec;

    std::cout << "请输入数据:" << std::endl;
    std::cout << "-1表示输入结束" << std::endl;

    while (true)
    {
        int n = 0;
        std::cin >> n;
        if (n == -1)
        {
            break;
        }
        vec.push_back(n);
    }

    Max<int> max;
    std::sort(vec.begin(), vec.end(), max);
    for (auto &i : vec)
    {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

void Test5()
{
    std::list<std::pair<int, char>> mylist;

    mylist.emplace_back(10, 'a');
    mylist.emplace_back(20, 'b');

    for (auto &i : mylist)
    {
        std::cout << i.first << " " << i.second << std::endl;
    }
}

void Test6()
{
    [] {};

    int a = 7, b = 1;
    auto ret = [=]
    { return a + b; };

    std::cout << ret() << std::endl;

    auto ret2 = [&](int c)
    { b = c + a; };
    ret2(7);
    std::cout << b << std::endl;

    auto ret3 = [=, &b](int c) -> int
    {
        return a + b + c;
    };

    std::cout << ret3(7) << std::endl;

    int x = 10;
    auto ret4 = [x]()
    { return x; };
    std::cout << ret4() << std::endl;
}

class A
{
public:
    A(std::string name, double salary, int num)
        : _name(name), _salary(salary), _num(num)
    {
    }

    std::string _name;
    double _salary;
    int _num;
};

void Test7()
{
    std::vector<A> vec = {{"苹果", 2.1, 5}, {"香蕉", 3, 4}, {"橙子", 2.2, 3}, {"菠萝", 1.5, 4}};
    std::sort(vec.begin(), vec.end(), [](const A &a, const A &b)
              { return a._salary > b._salary; });
    for (auto &i : vec)
    {
        std::cout << i._name.c_str() << " " << i._salary << " " << i._num << std::endl;
    }
    std::cout << "--------------------------" << std::endl;
    std::sort(vec.begin(), vec.end(), [](const A &a, const A &b)
              { return a._num > b._num; });
    for (auto &i : vec)
    {
        std::cout << i._name.c_str() << " " << i._salary << " " << i._num << std::endl;
    }
}

void Test8()
{
    std::function<int(int, int)> func = f;
    std::cout << func(10, 20) << std::endl;

    std::function<int(int, int)> func2 = Functor();
    std::cout << func2(10, 20) << std::endl;

    std::function<int(int, int)> func3 = [](const int &a, const int &b)
    { return a + b; };

    std::cout << func3(10, 20) << std::endl;

    std::function<int(int, int)> func4 = &Plus::plusi;
    std::cout << func4(10, 20) << std::endl;

    std::function<double(Plus,double, double)> func5 = &Plus::plusd;
    std::cout << func5(Plus(), 10.1, 20.2) << std::endl;
}

int main()
{
    // Test1();
    // Test2();

    // Test3();
    // Test4();
    //  Test5();
    // Test6();

   // Test7();
   Test8();
    return 0;
}